package com.ex

import com.android.SdkConstants
import com.android.build.api.transform.Format
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.internal.pipeline.TransformManager
import javassist.ClassPool
import org.apache.commons.io.FileUtils
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File

class CrashPlugin : Plugin<Project>, Transform() {


    private var android: AppExtension? = null
    private lateinit var project: Project
    val pool = ClassPool.getDefault()

    override fun apply(project: Project) {

        this.project = project
        if (project.plugins.hasPlugin(AppPlugin::class.java)) {
            print("found android project")
            project.dependencies.add("implementation", "cn.bmob.android:bmob-sdk:3.7.7")
            this.android = project.extensions.getByType(AppExtension::class.java)
//            android?.registerTransform(this)
        }

    }

    override fun getName(): String {
        return "crash_report_ts"
    }

    override fun getInputTypes(): MutableSet<QualifiedContent.ContentType> {
        return TransformManager.CONTENT_CLASS
    }

    override fun isIncremental() = false

    override fun getScopes(): MutableSet<in QualifiedContent.Scope> =
            TransformManager.SCOPE_FULL_PROJECT


    override fun transform(ts: TransformInvocation?) {
        super.transform(ts)

        print("crash start ---->")

        android?.bootClasspath?.forEach {
            pool.appendClassPath(it.absolutePath)
        }


        ts!!.inputs.forEach { input ->

            input.jarInputs.forEach { jarInput ->

                pool.insertClassPath(jarInput.file.absolutePath)
                val name = jarInput.name
                val destName = name.hashCode().toString()


                val dest = ts.outputProvider.getContentLocation(destName, jarInput.contentTypes, jarInput.scopes, Format.JAR)

                FileUtils.copyFile(jarInput.file, dest)
            }

            input.directoryInputs.forEach { dirInput ->

                dirInput.file.listFiles()?.forEach { classFile ->

                    pool.insertClassPath(classFile.absolutePath)

                    if (classFile.name.contains("MainActivity")) {
                        print("some message for crash :${classFile.name}")
                        doLogic(classFile)
                    }
                }

            }

        }
    }

    private fun doLogic(classFile: File) {

        val className = classFile.name.replace(SdkConstants.DOT_CLASS, "")
                .replace("\\", ".")
                .replace("/", ".")

        val clazz = pool.get(className)

        val method = clazz.getDeclaredMethod("onCreate")
        method?.apply {
            val codeBody = ""
            this.insertAfter(codeBody, true)
        }

    }

}